package com.qfedu.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.qfedu.dao.UserMapper;
import com.qfedu.dao.UserRepository;
import com.qfedu.pojo.entity.User;
import com.qfedu.pojo.req.UserReq;
import com.qfedu.pojo.resp.BaseResp;
import com.qfedu.service.UserService;
import com.qfedu.utils.MD5Utils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpSession;
import java.util.List;
import java.util.Random;

@Service
public class UserServiceImpl implements UserService {

    //邮件发送前的准备工作
    //1.注入UserRepository跟数据库进行连接，查询邮箱时用到
    @Autowired
    UserRepository userRepository;

    //2.定义发送邮件的人，即发件人的邮箱
    @Value("${spring.mail.username}")   //获取到配置文件中的发件人的邮箱
    private String sendUser;

    @Autowired
    JavaMailSender javaMailSender;

    @Autowired
    UserMapper userMapper;

    /**
     * 发送邮件验证的业务
     * @param email 前台传入的邮箱号
     * @param session   需要将验证码存入session中
     * @return
     */
    @Override
    public BaseResp sendMail(String email, HttpSession session) {
        //1.先通前台传入的过邮箱去数据库中进行查询
        User user = userRepository.findByEmail(email);
        //2..判断邮箱是否唯一，也就是判断通过邮箱能不能查到用户，如果查不到则说明没有该邮箱，则邮箱可以用于注册，反之不可以注册
        if(user != null) {  //说明查到了有邮箱信息的用户
            return new BaseResp(0, "该邮箱已被占用！", null, null);
        }
        //否则说明没有查到，也就是表中没有邮箱
        //3.设置基本的邮件发送结构/内容 --> 使用SimpleMailMessage();
        //3.1new一个邮件对象
        SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
        //3.2设置发件人
        simpleMailMessage.setFrom(sendUser);
        //3.3设置收件人，即注册时的用户使用的邮箱
        simpleMailMessage.setTo(email);
        //3.4设置邮件的主题/标题
        simpleMailMessage.setSubject("注册验证");
        //3.5设置发送的内容
        StringBuffer stringBuffer = new StringBuffer();
        for (int i = 0; i < 4; i++) {
            stringBuffer.append(new Random().nextInt(10));  //生成10以内的随机数
        }
        String code = stringBuffer.toString();
        simpleMailMessage.setText(code);
        //4.使用javaMailSender进行邮件发送
        javaMailSender.send(simpleMailMessage);
        //5.将发送的验证码，存在session中，key值为接收到的前端填写的邮箱后，之后用于进行对比
        session.setAttribute(email, code);
        return new BaseResp().Success();
    }

    /**
     * 注册的业务
     * @param userReq   前台传入的用户实体
     * @param session   需要从session中取出验证码
     * @return
     */
    @Override
    public BaseResp regist(UserReq userReq, HttpSession session) {
        //1.对比验证码是否一致
        Object attribute = session.getAttribute(userReq.getEmail());
        //1.1说明当前邮箱没有进行验证码的发送，所以在session中找不到验证码
        if(attribute == null) {
            return new BaseResp(0, "请先发送验证码！", null, null);
        }
        //1.2说明前台传入的验证码与session中的验证码不一致
        if(!userReq.getCode().equals(attribute)) {
            return new BaseResp(0, "验证码错误！", null, null);
        }
        //2.判断用户名是否重复
        User user = userRepository.findByUserName(userReq.getUserName());
        //说明前台传入的用户名在数据库中已经存在
        if(user != null) {
            return new BaseResp(0, "用户名重复！", null, null);
        }
        //3.如果前两条都不满足，说明验证码对比一致，用户名也不重复，则新增到数据库中
        //MD5加密操作
        String md5 = MD5Utils.createMd5(userReq.getUserName(), userReq.getPassword());
        User user1 = new User();
        BeanUtils.copyProperties(userReq, user1);
        user1.setPassword(md5);
//        userRepository.save(user1);
        userMapper.insertUser(user1);
        return new BaseResp(1, "注册成功！", null, null);
    }

    /**
     * 登录的业务
     * @param userReq   前端传入的用户实体
     * @return
     */
    @Override
    public BaseResp login(UserReq userReq) {
//        //1.根据前台传入的用户名去数据库中查询该条用户信息
//        User user = userRepository.findByUserName(userReq.getUserName());
//        //2.判断用户是否为空
//        if(user != null) {
//            //3.判断前台传入的密码是否与数据库中查询出的用户的密码一致
//            if(userReq.getPassword().equals(user.getPassword())) {
//                return new BaseResp(1, "登录成功！", null, null);
//            }
//        }
//        return new BaseResp(1, "登录失败！", null, null);

        //1.将前台传入的用户名和密码存入token中
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(userReq.getUserName(), userReq.getPassword());
        //2.通过安全管理器工厂获取到shiro的主体
        Subject subject = SecurityUtils.getSubject();
        try {
            //3.通过主体进行登录操作
            subject.login(usernamePasswordToken);
        } catch (UnknownAccountException unknownAccountException) {
            return new BaseResp(0, "用户名不存在！", null, null);
        } catch (IncorrectCredentialsException incorrectCredentialsException) {
            return new BaseResp(0, "密码错误！", null, null);
        }
        return new BaseResp(1, "登录成功！", null, null);
    }

    /**
     * 判断用户是否已登录的业务
     * @return success/error --> 成功/失败
     */
    @Override
    public BaseResp isAuthenticated() {
        Subject subject = SecurityUtils.getSubject();
        if(subject.isAuthenticated()) {
            return new BaseResp().Success();
        }
        return new BaseResp().Error();
    }

    @Override
    //Integer page, Integer size
    public BaseResp findAllUser(Integer page, Integer size) {
        //1.在执行全查之前开启分页
        PageHelper.startPage(page, size);
        //2.执行全查操作
        List<User> users = userMapper.findAllUser();
        //3.将查询结果放入分页对象中完成分页操作
        PageInfo<User> userPageInfo = new PageInfo<>(users);
        return new BaseResp(1, "查询成功", userPageInfo.getList(), userPageInfo.getTotal());
    }

    @Override
    public BaseResp updUser(UserReq userReq) {
        User user = new User();
        //将UserReq中接收的请求参数复制到user实体类中
        BeanUtils.copyProperties(userReq, user);
        userRepository.saveAndFlush(user);
        return new BaseResp(1, "修改成功！", null, null);
    }

    @Override
    public BaseResp delUser(UserReq userReq) {
        userRepository.deleteById(userReq.getId());
        return new BaseResp(1, "删除成功！", null, null);
    }


}
